<?php

/*
| +----------------------------------------------------------------------
| | DyCode 框架[为Dy自主开发框架]
| +----------------------------------------------------------------------
| | Copyright (c) 2015-2030 https://www.ngiveup.top/
| +----------------------------------------------------------------------
| | DyCode 提供个人非商业用途免费使用，商业需授权。
| +----------------------------------------------------------------------
| | Author: dy <wdyxzkq@qq.com>
| +----------------------------------------------------------------------
|
*/

namespace dy;

use dy\exception\RouteNotFoundException;

class Route
{
    /**
     * REST定义
     * @var array
     */
    protected $rest = [
        'index'  => ['get', '', 'index'],
        'create' => ['get', '/create', 'create'],
        'edit'   => ['get', '/<id>/edit', 'edit'],
        'read'   => ['get', '/<id>', 'read'],
        'save'   => ['post', '', 'save'],
        'update' => ['put', '/<id>', 'update'],
        'delete' => ['delete', '/<id>', 'delete'],
    ];

    /**
     * 请求方法前缀定义
     * @var array
     */
    protected $methodPrefix = [
        'get'    => 'get',
        'post'   => 'post',
        'put'    => 'put',
        'delete' => 'delete',
        'patch'  => 'patch',
    ];

    /**
     * 应用对象
     * @var App
     */
    protected $app;

    /**
     * 请求对象
     * @var Request
     */
    protected $request;

    /**
     * 当前HOST
     * @var string
     */
    protected $host;

    /**
     * 当前域名
     * @var string
     */
    protected $domain;

    /**
     * 当前分组对象
     */
    protected $group;

    /**
     * 获取路由实例
     * @return mixed
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * 注册路由规则
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param string $method 请求类型
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function rule($rule, $route, $method = '*', array $option = [], array $pattern = [])
    {
        //解析路由
        list($namespace, $action) = explode('@', $route);
        if (strpos($namespace, 'app\Controller') === false) {
            $namespace = 'app\Controller\\' . $namespace;
        }
        $rule = trim($rule,'/');

        // 创建路由规则实例
        $ruleItem = [
            'rule'   => $rule,
            'route'  => $route,
            'class'  => $namespace,
            'action' => $action,
        ];

        //添加路由解析
        if ($method === '*') {
            foreach ($this->methodPrefix as $key => $value) {
                $this->group[$key][$rule] = $ruleItem;
            }
        } else {
            $method                      = strtolower($method);
            $this->group[$method][$rule] = $ruleItem;
        }

        return $this->group;
    }

    /**
     * 注册路由分组
     * @access public
     * @param string|array $name 分组名称或者参数
     * @param array|\Closure $routes 分组路由
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function group($name, $routes, array $option = [], array $pattern = [])
    {
        foreach ($routes as $item => $value) {
            list($method, $rule, $route) = $value;

            $rule = $name . $rule;

            if(strtolower($method) == 'any'){
                $method = '*';
            }

            $this->rule($rule, $route, $method, $option, $pattern);
        }
    }

    /**
     * 注册路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function any($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, '*', $option, $pattern);
    }

    /**
     * 注册GET路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function get($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'GET', $option, $pattern);
    }

    /**
     * 注册POST路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function post($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'POST', $option, $pattern);
    }

    /**
     * 注册PUT路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function put($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'PUT', $option, $pattern);
    }

    /**
     * 注册DELETE路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function delete($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'DELETE', $option, $pattern);
    }

    /**
     * 注册PATCH路由
     * @access public
     * @param string $rule 路由规则
     * @param mixed $route 路由地址
     * @param array $option 路由参数
     * @param array $pattern 变量规则
     * @return array
     */
    public function patch($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'PATCH', $option, $pattern);
    }

    /**
     * 获取单个路由实例
     * @param $path
     * @param $method
     * @return array
     */
    public function routeCheck($path,$method)
    {
        //获取路由实例
        $route = $this->group[strtolower($method)][$path] ?? [];

        //路由不存在
        if (!$route) {
            throw new RouteNotFoundException();
        }

        return $route;
    }
}
